/* ==================================================================   
 * Created [2009-4-27 下午11:32:55] by Jon.King 
 * ==================================================================  
 * TSS 
 * ================================================================== 
 * mailTo:jinpujun@hotmail.com
 * Copyright (c) Jon.King, 2009-2012 
 * ================================================================== 
*/

package com.jinhe.tss.core.cachepool.strategy;

import com.jinhe.tss.core.cachepool.DefaultArithmetic;
import com.jinhe.tss.core.cachepool.DefaultCacheLoader;
import com.jinhe.tss.core.cachepool.IArithmetic;
import com.jinhe.tss.core.cachepool.ICacheLoader;
import com.jinhe.tss.core.cachepool.IPool;
import com.jinhe.tss.core.cachepool.ObjectPoolEvent;
import com.jinhe.tss.core.cachepool.container.IPoolContainer;
import com.jinhe.tss.core.cachepool.container.MapContainer;
import com.jinhe.tss.core.cachepool.proxy.Disabler;
import com.jinhe.tss.core.util.BeanUtil;

/** 
 * <p> CacheStrategy.java </p> 
 * <p></p>
 * 缓存策略 
 * <p></p>不变区
 * <p></p>  code
 * <p></p>  name
 * <p></p>可变区
 * <p></p>  普通，不触发池事件
 * <p></p>    accessMethod
 * <p></p>    disabled
 * <p></p>    interruptTime
 * <p></p>    remark
 * <p></p>  触发池事件STRATEGY_CHANGED_NORMAL
 * <p></p>    arithmeticClass
 * <p></p>    cacheLoaderClass
 * <p></p>    cyclelife
 * <p></p>  如果变大了则触发池事件STRATEGY_CHANGED_INITNUM_RISE,执行ObjectPool.startInitThread()；变小了不管。
 * <p></p>    initNum
 * <p></p>  如果变小了则触发池事件STRATEGY_CHANGED_SIZE_REDUCE,处理同PUT_IN事件；大了不管
 * <p></p>    poolSize
 * <p></p>  严重，触发池事件STRATEGY_CHANGED_RESET，重新初始化池
 * <p></p>    poolClass
 * <p></p>    poolCollectionClass
 * 
 * @author Jon.King 2006-12-29
 */
public class CacheStrategy{
    
    //缓存模块提供的对象池类型
    static final String SIMPLE_POOL_CLASS  = "com.jinhe.tss.core.cachepool.SimplePool";
    static final String BASE_POOL_CLASS    = "com.jinhe.tss.core.cachepool.ObjectPool";
    
    final static String DEFAULT_POOLCOLLECTION = MapContainer.class.getName();    
    final static String DEFAULT_ARITHMETIC = DefaultArithmetic.class.getName();
    final static String DEFAULT_LOADER = DefaultCacheLoader.class.getName();
    
    private String  name;          //缓存策略的名称
    private String  code;         //缓存策略的code
    private String  remark;      //缓存策略说明
    private Integer poolSize = 0;   //缓存池的容量（注： size 为零则表示不限定池大小）
    private Integer initNum = 0;    //初始化缓存池时初始缓存项的个数
    private Long    cyclelife = 0L;      //池中元素的有效期（生命周期）
    private Long    interruptTime = 0L;  //中断时间(取不到缓存项时执行其他操作的等待时间)
    private String  disabled = CacheConstants.FALSE;     //1:停用， 0：启用（用以检测缓存启用和停用时的执行效率）
    private String  visible = CacheConstants.TRUE;      //1:显示， 0：隐藏 是否展示，用以隐藏运行时创建过来的缓存池，像没有名字只有code的那些
    
    /**
     * 池的访问方式
     * 1: FIFO   (first-in, first-out: a queue).
     * 2: LIFO   (last-in, first-out: a stack).
     * 3: RANDOM (a random connection is selected for check-out).
     * 4：ACCESS_LRU （最近使用）
     * 5：ACCESS_LFU  （最不常使用）
     */
    private Integer accessMethod = IPoolContainer.ACCESS_RANDOM; 
    
    private String poolClass = SIMPLE_POOL_CLASS;  //缓存池实现类
    private String poolCollectionClass = DEFAULT_POOLCOLLECTION; //池容器类,默认为：MapPool.class。在特定情形下用特定的集合类或许可以提高性能

    private String arithmeticClass = DEFAULT_ARITHMETIC;  //执行缓存算法的类
    private String cacheLoaderClass = DEFAULT_LOADER;    //重新载入缓存项的类
    
    private IPool pool; //缓存策略里定义的缓存池
   
    public IPool getPoolInstance(){
        if(pool != null && pool.getCacheStrategy().equals(this))
            return pool;
        
        pool = (IPool)BeanUtil.newInstanceByName(poolClass);
        pool.setCacheStrategy(this);
        pool = (IPool) Disabler.disableWrapper(pool);
        
        pool.setArithmetic((IArithmetic) BeanUtil.newInstanceByName(arithmeticClass));
        pool.setLoader((ICacheLoader) BeanUtil.newInstanceByName(cacheLoaderClass));
        //需要放到最后一句，因为初始化需要用到IArithmetic.create()
        pool.init();
        
        return pool;
    }
    
    public boolean equals(Object o){
        if(o instanceof CacheStrategy){
            CacheStrategy strategy = (CacheStrategy) o;
            return this.code.equals(strategy.getCode());
        }
        return false;
    }
    
    /**
     * 缓存策略修改时重新设置各个策略项的值，同时触发相应的事件。
     * @param c
     */
    public void fireEventIfChanged(CacheStrategy c){
        // 缓存项生命周期、载入器、缓存池执行算法发生了改变时：
        if(!this.cyclelife.equals(c.getCyclelife())
                || !this.cacheLoaderClass.equals(c.getCacheLoaderClass())
                || !this.arithmeticClass.equals(c.getArithmeticClass())){
            
            this.cyclelife = c.getCyclelife();
            this.cacheLoaderClass = c.getCacheLoaderClass();
            this.arithmeticClass = c.getArithmeticClass();
            pool.firePoolEvent(ObjectPoolEvent.STRATEGY_CHANGED_NORMAL);
        }
        
        if(this.initNum.compareTo(c.getInitNum()) < 0){ // 初始化个数变少
            this.initNum = c.getInitNum();
            pool.firePoolEvent(ObjectPoolEvent.STRATEGY_CHANGED_INITNUM_RISE);
        }
        
        if(this.poolSize.compareTo(c.getPoolSize()) > 0){ // 池变小
            this.poolSize = c.getPoolSize();
            pool.firePoolEvent(ObjectPoolEvent.STRATEGY_CHANGED_SIZE_REDUCE);
        }
        
        if(!this.poolClass.equals(c.getPoolClass()) || !this.poolCollectionClass.equals(c.getPoolCollectionClass())){
            this.poolClass = c.getPoolClass();
            this.poolCollectionClass = c.getPoolCollectionClass();
            pool.firePoolEvent(ObjectPoolEvent.STRATEGY_CHANGED_RESET);
        } 
        
        this.initNum = c.getInitNum();
        this.poolSize = c.getPoolSize();
        this.accessMethod = c.getAccessMethod();
        this.disabled = c.getDisabled();
        this.interruptTime = c.getInterruptTime();
        this.remark = c.getRemark();
    }
    
    /**
     * 设置缓存策略的arithmeticClass。同时改变池的arithmetic对象，如果池已经存在的话。
     */
    public void setArithmeticClass(String arithmeticClass) {
        this.arithmeticClass = arithmeticClass == null || arithmeticClass.equals("")? DEFAULT_ARITHMETIC : arithmeticClass;
    }
    /**
     * 设置缓存策略的cacheLoaderClass。同时改变池的cacheLoader对象，如果池已经存在的话。
     */
    public void setCacheLoaderClass(String cacheLoaderClass) {
        this.cacheLoaderClass = cacheLoaderClass == null || cacheLoaderClass.equals("")? DEFAULT_LOADER : cacheLoaderClass;
    }
    /**
     * 设置缓存池类型
     */
    public void setPoolClass(String poolClass) {
        this.poolClass = poolClass == null || poolClass.equals("")? SIMPLE_POOL_CLASS : poolClass;
    }
    /**
     * 设置缓存池的容器类
     */
    public void setPoolCollectionClass(String poolCollectionClass) {
        this.poolCollectionClass = poolCollectionClass == null || poolCollectionClass.equals("")? DEFAULT_POOLCOLLECTION : poolCollectionClass;
    }
    
    public void setCyclelife(Long cyclelife) { this.cyclelife = cyclelife == null ? 0 : cyclelife; }
 
    public String getArithmeticClass() { return arithmeticClass; }
 
    public String getCacheLoaderClass() { return cacheLoaderClass; }
  
    public String getCode() { return code; }
    
    public Long getCyclelife() { return cyclelife; }
 
    public String getDisabled() { return disabled; }
   
    public Long getInterruptTime() { return interruptTime ; }
 
    public String getName() { return name; }
 
    public Integer getPoolSize() { return poolSize; }
 
    public void setCode(String code) { this.code = code; }
 
    public void setDisabled(String disabled) { this.disabled = disabled; }
 
    public void setInterruptTime(Long interruptTime) { this.interruptTime = interruptTime == null ? 0 : interruptTime; }
 
    public void setName(String name) { this.name = name == null ? code : name; }
 
    public void setPoolSize(Integer poolSize) {
        if(poolSize != null){
            int size = Math.max(0, poolSize);  //确保 size 不小于 0
            this.poolSize = new Integer(size);
        }
    }
 
    public String getPoolClass() { return poolClass; }

    public String getPoolCollectionClass() { return poolCollectionClass; }
 
    public Integer getInitNum() { return initNum; }

    public void setInitNum(Integer initNum) { this.initNum = (initNum == null ? 0 : initNum) ;}
    
    public Integer getAccessMethod() { return accessMethod; }
    
    public void setAccessMethod(Integer method) { this.accessMethod = method;}
    
    public String getRemark() { return remark; }
 
    public void setRemark(String remark) { this.remark = remark; }
    
    public String getVisible() { return visible; }

    public void setVisible(String visible) { this.visible = visible; }
}

